/**
 * Copyright 2012 ibiblio
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ibiblio.terasaur.item

import org.ibiblio.terasaur.controller.ParamsHelper
import org.ibiblio.terasaur.item.Collection
import grails.plugins.springsecurity.Secured
import org.ibiblio.terasaur.ui.StringCleaner
import org.ibiblio.terasaur.ui.UrlHelper
import org.ibiblio.terasaur.controller.ItemMixin

@Secured(['ROLE_ADMIN', 'IS_AUTHENTICATED_FULLY'])
@Mixin(ItemMixin)
class CollectionController {
    def scaffold = Collection
    static defaultAction = "index"
    def searchService // injected
    static ParamsHelper _paramsHelper = new ParamsHelper()
    static StringCleaner _stringCleaner = new StringCleaner()
    static UrlHelper urlHelper = new UrlHelper()

    @Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
    def index = {
        redirect(controller:"browse", action: "recent")
    }

    /**
     * Browse collection by id.  Sort by publication date, desc.
     */
    @Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
    def browse = {
        _executeSearch('browse')
    }

    /**
     * Search collection.  Sort by publication date, desc.
     */
    @Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
    def search = {
        if (!params.query) {
            redirect(controller:"browse", action: "recent")
            return
        }
        _executeSearch('search')
    }

    private void _executeSearch(String action) {
        def collection = _getCollectionInstance()
        if (!collection) {
            redirect(controller:"browse", action: "recent")
            return
        }

        def searchParams = _getSearchParams(action, collection)
        def result = searchService.query(searchParams)

        Map map = _getResponseMap(action, result, collection)
        if (result.itemList) {
            map.itemList = result.itemList
            map.itemListTotal = result.documentList.numFound
        } else {
            map.itemList = []
            map.itemListTotal = 0
        }

        if (result.error) {
            flash.message = message(code:result.error)
        }

        render(view:"/item/list", model:map)
    }

    private Map _getSearchParams(String action, Collection collection) {
        Map searchParams = _paramsHelper.getOffsetMax(params)
        if (action == 'search') {
            searchParams.query = params.query
        } else {
            searchParams.rawQuery = '*:*'
        }
        searchParams.filters = ['collection_id:' + collection.id]
        return searchParams
    }

    private Map _getResponseMap(String action, Map result, Collection collection) {
        // Note that controller and action are reversed for link generation
        String label = _getPageLabel(action, result, collection)
        def urlName = _stringCleaner.clean(collection.name)

        Map map = [
            pageTitle: label,
            listLabel: label,
            itemListType: 'solr',
            showCollection: false,
            error: (result.error) ? true : false,
            searchUrl: urlHelper.collectionLink(collection, 'search'),
            browseUrl: urlHelper.collectionLink(collection, 'browse'),
            collectionLogo: getCollectionLogo(collection),
            paginationParams: [controller:action, action:'collection', name:urlName, id:collection.id]
        ]
        if (action == 'search') {
            map.paginationParams.query = params.query
            map.searchQueryText = result.query
        }
        return map
    }

    private String _getPageLabel(String action, Map result, Collection collection) {
        String label
        if (action == 'search') {
            label = message(code:'item.search.collection.label', args:[result.query, collection.name])
        } else {
            label = message(code:'item.browse.collection.label', args:[collection.name])
        }
        return label
    }

    /**
     * Helper functions
     */
    private Collection _getCollectionInstance() {
        Collection c = null
        if (!params.id) {
            return
        }

        Long collectionId = Long.parseLong(params.id)
        c = Collection.get(collectionId)
        return c
    }

}
